

import { engine } from "../../engine/engine";
import { LocalDataType } from "./DBDefine";

type TypeMapType = { [key: string]: any };

/**
 * 表的解析器
 */
export class TableParser {

    private _insertStr = ''//: '(id,pass,levels) VALUES (?,?,?)',
    private _insertAllStr = ''//: '(id,pass,levels) VALUES (@id, @pass, @levels)',
    private _updateAllStr = ''//: 'set pass=@pass,levels=@levels where id=@id',
    private _deleteAllStr = '' //: 'where id=@id',
    private _primaryKeyName = ''
    private _typeMap: TypeMapType = {};
    private _typeStr = ''
    constructor(tableDefine: string) {

        this._typeStr = this.changeToSqlStr(tableDefine) //.replace(/boolean/g, 'integer');

        let result = tableDefine.match(/\s*(\b[\w_$][\w\d_$]*\b)[\s\S]*/i)

        if (result) {
            // console.log('primaryKeyName result ', result)
            let primaryKeyName = result[1]
            this._primaryKeyName = primaryKeyName;
            let typeNames: string[] = []
            let types: string[] = []
            let list = tableDefine.split(',')
            for (let index = 0; index < list.length; index++) {
                const element = list[index];
                let result = element.match(/\s*(\b[\w_$][\w\d_$]*\b)\s*(\b[\w_$][\w\d_$]*\b)[\s\S]*/i)
                if (result) {
                    typeNames.push(result[1])
                    types.push(result[2])
                }
            }
            if (typeNames.length != types.length) {
                engine.error('类型和名称长度不一致')
            }


            // LogUtils.log(' types', types)
            if (typeNames.length > 0) {
                for (let index = 0; index < typeNames.length; index++) {
                    const keyName = typeNames[index];
                    const typeName = types[index]
                    this._typeMap[keyName] = typeName;
                }
                let temp = []
                this._insertStr = '('
                this._insertStr += typeNames.join(',');
                this._insertStr += ') VALUES ('
                for (let index = 0; index < typeNames.length; index++) {
                    temp.push('?')
                }
                this._insertStr += temp.join(',')
                this._insertStr += ')'


                temp = []
                this._insertAllStr = '('
                this._insertAllStr += typeNames.join(',');
                this._insertAllStr += ') VALUES ('
                for (let index = 0; index < typeNames.length; index++) {
                    const element = typeNames[index];
                    temp.push('@' + element)
                }
                this._insertAllStr += temp.join(',')
                this._insertAllStr += ')'

                temp = []
                this._updateAllStr = 'set '
                for (let index = 0; index < typeNames.length; index++) {
                    const element = typeNames[index];
                    if (element != primaryKeyName) {
                        temp.push(element + '=@' + element)
                    }
                }
                this._updateAllStr += temp.join(',')

                this._updateAllStr += ' where ' + primaryKeyName + '=@' + primaryKeyName

                this._deleteAllStr += 'where ' + primaryKeyName + '=@' + primaryKeyName


                // LogUtils.log(' this._insertStr ', this._insertStr)
                // LogUtils.log(' this._insertAllStr ', this._insertAllStr)
                // LogUtils.log(' this._updateAllStr ', this._updateAllStr)
                // LogUtils.log(' this._deleteAllStr ', this._deleteAllStr)
            } else {
                engine.warn('类型解析失败')
            }
        } else {
            engine.warn('类型解析失败', tableDefine)
        }
    }

    get primaryKeyName() {
        return this._primaryKeyName;
    }
    get typeStr() {
        return this._typeStr;
    }

    get insertStr() {
        return this._insertStr;
    }
    get insertAllStr() {
        return this._insertAllStr;
    }
    get updateAllStr() {
        return this._updateAllStr;
    }
    get deleteAllStr() {
        return this._deleteAllStr;
    }

    get typeMap() {
        return this._typeMap;
    }
    changeToSqlStr(str: string) {
        let temp = str.replace(/\bboolean\b/ig, 'real');
        temp = temp.replace(/\bobject\b/ig, 'text');
        return temp;
    }

    exchangeValueToSql(data: any, key: string) {
        let typeName = this.typeMap[key]
        if (typeName.match(/\bobject\b/ig)) {
            if (data == null || data == undefined) {
                return ''
            } else {
                return JSON.stringify(data)
            }
        } else if (typeName.match(/\bboolean\b/ig)) {
            return data ? 1 : 0
        } else {
            return data;
        }
    }

    exchangeValueToJs(data: any, key: string) {
        let typeName = this.typeMap[key]
        if (typeName.match(/\bobject\b/ig)) {
            if (data == '') {
                return null;
            } else {
                return JSON.parse(data)
            }
        } else if (typeName.match(/\bboolean\b/ig)) {
            return data == 1 || data == 1.0 ? true : false;
        } else {
            return data;
        }
    }

    exchangeListToJS(list: LocalDataType[]) {
        let temp = list//JSON.parse(JSON.stringify(list))
        for (let index = 0; index < temp.length; index++) {
            const object = temp[index];
            for (const key in object) {
                object[key] = this.exchangeValueToJs(object[key], key)
            }
        }
        return temp;
    }

    exchangeListToSql(list: LocalDataType[]): LocalDataType[] {
        try {
            let temp = JSON.parse(JSON.stringify(list))
            for (let index = 0; index < temp.length; index++) {
                const object = temp[index];
                for (const key in object) {
                    object[key] = this.exchangeValueToSql(object[key], key)
                }
            }
            return temp;
        } catch (error) {
            engine.error(' error ', error)
            engine.log(' list ', list)
            return []
        }

    }
}